﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using WMS.FC.Domain.DomainObject.System;
using WMS.FC.Domain.DomainObject.Tray;
using WMS.FC.Domain.PersistenceObject.Business;
using WMS.FC.Domain.Repository;
using WMS.FC.Domain.Service.System;
using WMS.FC.Domain.Service.Tray.Interface;

namespace WMS.FC.Domain.Service.Tray
{
    public class GetTrayInfoService : ServiceBase, IGetTrayInfoService
    {
        protected readonly ITrayRepository trayRepository;
        protected readonly IMaterialRepository materialRepository;
        protected readonly ITechnologyRepository technologyRepository;

        public GetTrayInfoService(
            ILogger<ServiceBase> logger,
            IOptions<WmsSettings> options,
            IMapper mapper,
            ITrayRepository trayRepository,
            IMaterialRepository materialRepository,
            ITechnologyRepository technologyRepository)
            : base(logger, options, mapper)
        {
            this.trayRepository = trayRepository;
            this.materialRepository = materialRepository;
            this.technologyRepository = technologyRepository;
        }

        public async Task<ActionResult<TrayDO>> GetWCSTrayInfo(string? trayBarcode, UserInfo userInfo)
        {
            var result = new ActionResult<TrayDO>("获取托盘信息");
            try
            {
                if (string.IsNullOrWhiteSpace(trayBarcode))
                    return result.ArgumentError("托盘条码不能为空");

                var data = new TrayDO();
                var trayPO = await trayRepository.GetTrayByBarcode(trayBarcode);
                if (trayPO == null)
                    return result.BusinessError($"托盘条码:({trayBarcode}),未登录");

                data.CurrentTray = trayPO;
                var materialPO = await materialRepository.GetMaterialByCode(trayPO.MaterialCode);
                if (materialPO == null)
                    return result.BusinessError($"物料编码:({trayPO.MaterialCode}),物料数据未找到");

                data.TrayMaterial = materialPO;
                var technologyProcessPO = await technologyRepository.GetTechnologyProcess(trayPO.TechnologyProcessCode);
                if (technologyProcessPO == null)
                    return result.BusinessError($"工艺工序:({trayPO.TechnologyProcessCode}),工艺工序数据未找到");

                data.CurrentTechnologyProcess = technologyProcessPO;
                var cellPOList = await trayRepository.GetTrayCellList(trayBarcode);
                for (var i = 0; i < materialPO.FillQuantity; i++)
                {
                    var cellPO = cellPOList.FirstOrDefault(entity => entity.CellPosition == (i + 1));
                    if (cellPO == null)
                    {
                        cellPO = new CellPO()
                        {
                            CellPosition = i + 1,
                        };
                    }

                    data.CellList.Add(cellPO);
                }

                result.Data = data;
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }

        public async Task<ActionResult<TrayDO>> GetTrayInfo(string trayBarcode, bool isContainTrayList, bool isContianCellMaterial, bool isContainRoute, bool isContainProcess, bool isContainRouteProcess, bool isContainRouteProcessList, UserInfo userInfo)
        {
            var result = new ActionResult<TrayDO>("获取托盘信息");
            try
            {
                if (string.IsNullOrWhiteSpace(trayBarcode))
                    return result.ArgumentError("托盘条码不能为空");

                var data = new TrayDO();
                var trayPO = await trayRepository.GetTrayByBarcode(trayBarcode);
                if (trayPO == null)
                    return result.BusinessError($"托盘条码:({trayBarcode}),未登录");

                data.CurrentTray = trayPO;
                if (isContainTrayList)
                {
                    data.TrayList = await trayRepository.GetTrayListByBarcode(trayBarcode);
                    if (data.TrayList == null || data.TrayList.Count < 1)
                        return result.BusinessError($"托盘条码:({trayBarcode}),获取托盘组异常");
                }

                var trayMaterialPO = await materialRepository.GetMaterialByCode(trayPO.MaterialCode);
                if (trayMaterialPO == null)
                    return result.BusinessError($"物料编码:({trayPO.MaterialCode}),物料数据未找到");

                data.TrayMaterial = trayMaterialPO;

                if (isContainRoute)
                {
                    var technologyRoutePO = await technologyRepository.GetTechnologyRoute(trayPO.TechnologyRouteCode);
                    if (technologyRoutePO == null)
                        return result.BusinessError($"工艺路径:({trayPO.TechnologyRouteCode}),工艺路径数据未找到");

                    data.CurrentTechnologyRoute = technologyRoutePO;

                }

                if (isContainProcess)
                {
                    var technologyProcessPO = await technologyRepository.GetTechnologyProcess(trayPO.TechnologyProcessCode);
                    if (technologyProcessPO == null)
                        return result.BusinessError($"工艺工序:({trayPO.TechnologyProcessCode}),工艺工序数据未找到");

                    data.CurrentTechnologyProcess = technologyProcessPO;
                }

                if (isContainRouteProcess)
                {
                    var technologyRouteProcessPO = await technologyRepository.GetTechnologyRouteProcess(trayPO.TechnologyRouteCode, trayPO.TechnologyProcessCode);
                    if (technologyRouteProcessPO == null)
                        return result.BusinessError($"工艺路径:({trayPO.TechnologyRouteCode}),工艺工序:({trayPO.TechnologyProcessCode}),工艺路径工序数据未找到");

                    data.CurrentTechnologyRouteProcess = technologyRouteProcessPO;
                }

                if (isContainRouteProcessList)
                {
                    var technologyRouteProcessPOList = await technologyRepository.GetTechnologyRouteProcessList(trayPO.TechnologyProcessCode);
                    data.TechnologyRouteProcessList = technologyRouteProcessPOList;
                }

                if (isContainTrayList)
                {
                    var trayBarcodeList = data.TrayList!.Select(entity => entity.Barcode).ToList();
                    var cellPOList = await trayRepository.GetTrayCellList(trayBarcodeList);
                    foreach (var tray in data.TrayList!)
                    {
                        for (var i = 0; i < trayMaterialPO.FillQuantity; i++)
                        {
                            var cellPO = cellPOList.FirstOrDefault(entity => entity.CellPosition == (i + 1));
                            if (cellPO == null)
                            {
                                cellPO = new CellPO()
                                {
                                    CellPosition = i + 1,
                                };
                            }

                            data.CellList.Add(cellPO);
                        }
                    }
                }
                else
                {
                    var cellPOList = await trayRepository.GetTrayCellList(trayBarcode);
                    for (var i = 0; i < trayMaterialPO.FillQuantity; i++)
                    {
                        var cellPO = cellPOList.FirstOrDefault(entity => entity.CellPosition == (i + 1));
                        if (cellPO == null)
                        {
                            cellPO = new CellPO()
                            {
                                CellPosition = i + 1,
                            };
                        }

                        data.CellList.Add(cellPO);
                    }
                }

                if (isContianCellMaterial)
                {
                    var cellPO = data.CellList.FirstOrDefault(cell => cell.Barcode.StartsWith(options.Value.FakeCellBarcodePrefix, StringComparison.InvariantCultureIgnoreCase));
                    if (cellPO != null)
                    {
                        var cellMaterialPO = await materialRepository.GetMaterialByCode(cellPO.MaterialCode);
                        if (cellMaterialPO == null)
                            return result.BusinessError($"物料编码:{cellPO.MaterialCode},物料数据未找到");

                        data.CellMaterial = cellMaterialPO;
                    }
                }

                result.Data = data;
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }
    }
}
